package util

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strings"

	"github.com/mitchellh/mapstructure"
)

type RawObject struct {
	Code  string      `json:"code"`
	Total int         `json:"total"`
	Data  [][]RawItem `json:"data"`
}

type RawItem struct {
	F string      `json:"f"`
	V interface{} `json:"v"`
}

type Result struct {
	Id      string   `json:"id"`
	Title   string   `json:"tit"`
	Year    []string `json:"yea"`
	Issue   []string `json:"iss"`
	Key     []string `json:"key"`
	Authors []string `json:"authors"`
	SubType []string `json:"-"`
}

func (r *Result) String() string {
	return fmt.Sprintf("id: %s, title: %v, year: %v, Issue: %v, Key: %v, authors: %v, subtype: %v", r.Id, r.Title, r.Year, r.Issue, r.Key, r.Authors, r.SubType)
}

func Transfer(msg string) []*Result {

	var data RawObject
	if err := json.Unmarshal([]byte(msg), &data); err == nil {
		fmt.Println(data.Total)
	} else {
		fmt.Println(err)
	}

	var results []*Result

	// for range方式
	for _, v := range data.Data {
		r := transfer(v)
		results = append(results, r)
	}

	//allstudentjson, _ := json.Marshal(results)
	//fmt.Println(string(allstudentjson))

	return results
}

func transfer(v []RawItem) *Result {
	result := &Result{}

	for i, item := range v {

		fmt.Println(i, item, "begin")
		switch item.F {
		case "id":
			result.Id = item.V.(string)
		case "tit":
			result.Title = filterTitleList(getStringSlice(item.V))
		case "yea":
			result.Year = getStringSlice(item.V)
		case "iss":
			result.Issue = getStringSlice(item.V)
		case "key":
			result.Key = getStringSlice(item.V)
		case "hasAut":
			result.Authors = getKeySlice(item.V)
		case "sysuty":
			result.SubType = getStringSlice(item.V)
		default:
			fmt.Println(i, item, "(unknown)")
		}

	}
	return result
}

func getStringSlice(obj interface{}) []string {
	var list []string
	if reflect.TypeOf(obj).Kind() == reflect.Slice {
		s := reflect.ValueOf(obj)
		for i := 0; i < s.Len(); i++ {
			ele := s.Index(i)
			list = append(list, filterTitle(ele.Interface().(string)))
		}
	} else {
		panic(obj)
	}
	return list
}

func getKeySlice(obj interface{}) []string {
	var list []string
	if reflect.TypeOf(obj).Kind() == reflect.Slice {
		s := reflect.ValueOf(obj)
		for i := 0; i < s.Len(); i++ {
			ele := s.Index(i)
			rawItemList := getRawItemSlice(ele.Interface())
			for _, item := range rawItemList {
				if item.F == "nam" {
					list = append(list, getStringSlice(item.V)...)
				}
			}
			//list = append(list, ele.Interface().(string))
		}
	} else {
		panic(obj)
	}
	return list
}

func getRawItemSlice(obj interface{}) []RawItem {
	var list []RawItem
	if reflect.TypeOf(obj).Kind() == reflect.Slice {
		s := reflect.ValueOf(obj)
		for i := 0; i < s.Len(); i++ {
			ele := s.Index(i)
			ri := RawItem{}
			mapstructure.Decode(ele.Interface(), &ri)
			list = append(list, ri)
		}
	} else {
		panic(obj)
	}
	return list
}

func filterTitleList(ss []string) string {
	r := ""
	for _, s := range ss {
		s = strings.ReplaceAll(s, "<em>", "")
		s = strings.ReplaceAll(s, "</em>", "")
		r = r + s
	}
	return r
}

func filterTitle(s string) string {

	s = strings.ReplaceAll(s, "<em>", "")
	s = strings.ReplaceAll(s, "</em>", "")
	return s
}
